package com.deng.seata.at.order.config;

import com.alibaba.druid.pool.DruidDataSource;
import io.seata.rm.datasource.DataSourceProxy;
import io.seata.rm.datasource.xa.DataSourceProxyXA;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;


/**
 * 依赖 seata-spring-boot-starter 时，自动代理数据源，无需额外处理，默认是AT模式
 * 依赖 seata-all 时，使用 @EnableAutoDataSourceProxy (since 1.1.0) 注解，注解参数可选择 jdk 代理或者 cglib 代理。
 * 依赖 seata-all 时，也可以手动使用 DatasourceProxy 来包装 DataSource。
 *
 * @Desc: 新增DataSourceConfiguration.java，Seata的RM通过DataSourceProxy才能在业务代码的事务提交时，
 *        通过这个切入点，与TC进行通信互换，记录undo_log等
 */
@Configuration
public class DataSourceConfiguration {


    @Bean("druidDataSource")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource druidDataSource(){
        return new DruidDataSource();
    }

    // Seata是通过代理数据源实现分支事务的，所以需要配置io.seata.rm.datasource.DataSourceProxy的Bean，
    // 必须满足以下条件，否则事务不会回滚，无法实现分布式事务：
    //  1、undo_log必须和开启全局事务的要操作的表放在同一个库
    //  2、必须用@Primary标注默认数据源
    //  3、开启全局事务与本地事务，用@GlobalTransactional和@Transactional(rollbackFor = Exception.class)标注方法
    //  4、分支事务的项目配置文件必须配置(默认也是true) seata.enable-auto-data-source-proxy: true
    @Primary
    @Bean("dataSourceProxy")
    public DataSource dataSourceProxy(@Qualifier("druidDataSource") DataSource druidDataSource){
//      AT模式
        return new DataSourceProxy(druidDataSource);
        // XA模式
//        return new DataSourceProxyXA(druidDataSource1);
    }
}
